#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#include "ohos_init.h"
#include "cmsis_os2.h"

// WiFi & 网络相关
#include "hi_wifi_api.h"
#include "lwip/ip_addr.h"
#include "lwip/netifapi.h"
#include "lwip/sockets.h"

// 硬件 IO 相关
#include "hi_io.h"
#include "hi_gpio.h"
#include "hi_errno.h"

// MQTT 相关
#include "MQTTClient.h"

// --- 宏定义配置 ---
// 按键 GPIO 定义，请根据你的硬件实际接线修改
#define F1_KEY 11
#define F2_KEY 12

// WiFi 信息
#define WIFI_SSID     "***"
#define WIFI_PASSWORD "z012345678123"

// MQTT 信息
#define MQTT_BROKER   "broker.emqx.io"
#define MQTT_PORT     1883
#define MQTT_TOPIC    "24iot01/team12" // 发布消息的主题

// MQTT 账户信息
#define MQTT_CLIENTID "mqttx_abc53a1f_device" // 建议设备端和电脑端客户端ID区分开
#define MQTT_USER     "device0112_th"
#define MQTT_PASS     "123456"

// --- 全局变量 ---
static int g_wifi_connected = 0;
static struct netif *g_lwip_netif = NULL;

static MQTTClient mq_client;
static Network n;
static unsigned char *mqtt_buf = NULL;
static unsigned char *mqtt_readbuf = NULL;
static const int buf_size = 4096;

// 按键标志位，使用 volatile 关键字确保编译器不优化
static volatile int g_f1_flag = 0;
static volatile int g_f2_flag = 0;

// --- 1. 按键中断处理 ---
static void F1_OnPressed(char *arg) {
    (void)arg;
    g_f1_flag = 1;
    printf(">> Key F1 Triggered, flag set.\r\n");
}

static void F2_OnPressed(char *arg) {
    (void)arg;
    g_f2_flag = 1;
    printf(">> Key F2 Triggered, flag set.\r\n");
}

static void Button_Init(void) {
    printf("Initializing Buttons...\r\n");
    hi_gpio_init();

    // 配置 F1 按键
    hi_io_set_func(F1_KEY, HI_IO_FUNC_GPIO_11_GPIO);
    hi_io_set_pull(F1_KEY, HI_IO_PULL_UP); // 上拉，按键按下为低电平
    hi_gpio_set_dir(F1_KEY, HI_GPIO_DIR_IN);
    // 注册下降沿中断
    hi_gpio_register_isr_function(F1_KEY, HI_INT_TYPE_EDGE, HI_GPIO_EDGE_FALL_LEVEL_LOW, &F1_OnPressed, NULL);
    
    // 配置 F2 按键
    hi_io_set_func(F2_KEY, HI_IO_FUNC_GPIO_12_GPIO);
    hi_io_set_pull(F2_KEY, HI_IO_PULL_UP);
    hi_gpio_set_dir(F2_KEY, HI_GPIO_DIR_IN);
    hi_gpio_register_isr_function(F2_KEY, HI_INT_TYPE_EDGE, HI_GPIO_EDGE_FALL_LEVEL_LOW, &F2_OnPressed, NULL);
    
    printf("Buttons initialized.\r\n");
}

// --- 2. WiFi 连接逻辑 ---
void wifi_event_cb(const hi_wifi_event *hisi_event) {
    if (hisi_event == NULL) return;
    switch (hisi_event->event) {
        case HI_WIFI_EVT_CONNECTED:
            printf("WiFi Connected! Starting DHCP...\r\n");
            netifapi_dhcp_start(g_lwip_netif);
            g_wifi_connected = 1;
            break;
        case HI_WIFI_EVT_DISCONNECTED:
            printf("WiFi Disconnected!\r\n");
            g_wifi_connected = 0;
            break;
        default: 
            printf("WiFi Event: %d\r\n", hisi_event->event);
            break;
    }
}

int Wifi_Connect(void) {
    int ret;
    char ifname[WIFI_IFNAME_MAX_SIZE + 1] = {0};
    int len = sizeof(ifname);
    
    ret = hi_wifi_sta_start(ifname, &len);
    if (ret != HISI_OK) {
        printf("hi_wifi_sta_start failed, ret=%d\r\n", ret);
        return -1;
    }
    printf("WiFi STA started, interface name: %s\r\n", ifname);

    hi_wifi_register_event_callback(wifi_event_cb);
    g_lwip_netif = netifapi_netif_find(ifname);
    if (g_lwip_netif == NULL) {
        printf("netifapi_netif_find failed\r\n");
        return -1;
    }

    hi_wifi_assoc_request assoc_req = {0};
    assoc_req.auth = HI_WIFI_SECURITY_WPA2PSK;
    memcpy(assoc_req.ssid, WIFI_SSID, strlen(WIFI_SSID));
    memcpy(assoc_req.key, WIFI_PASSWORD, strlen(WIFI_PASSWORD));
    
    printf("Connecting to WiFi: %s ...\r\n", WIFI_SSID);
    ret = hi_wifi_sta_connect(&assoc_req);
    if (ret != HISI_OK) {
        printf("hi_wifi_sta_connect failed, ret=%d\r\n", ret);
        return -1;
    }
    
    return 0;
}

// --- 3. MQTT 业务逻辑 ---
void mqtt_msg_cb(MessageData *msg_data) {
    // 这个回调函数会在收到订阅主题的消息时触发
    printf("MQTT Message Received:\r\n");
    printf("  Topic: %.*s\r\n", msg_data->topicName->lenstring.len, msg_data->topicName->lenstring.data);
    printf("  Payload: %.*s\r\n", msg_data->message->payloadlen, (char*)msg_data->message->payload);
}

void Publish_Msg(const char* payload) {
    if (payload == NULL) {
        printf("Publish_Msg: payload is NULL\r\n");
        return;
    }
    
    MQTTMessage message;
    message.qos = 0;
    message.retained = 0;
    message.payload = (void *)payload;
    message.payloadlen = strlen(payload);
    
    int rc = MQTTPublish(&mq_client, MQTT_TOPIC, &message);
    if (rc != 0) {
        printf("MQTT Publish Failed! rc=%d, Payload: %s\r\n", rc, payload);
    } else {
        printf("MQTT Publish Success! Payload: %s\r\n", payload);
    }
}

void ButtonMqttTask(void *arg) {
    (void)arg;
    
    // 初始化按键
    Button_Init();
    
    // 连接 WiFi
    if (Wifi_Connect() != 0) {
        printf("WiFi Initialization Failed. Task exiting.\r\n");
        return;
    }
    
    // 等待 WiFi 连接成功
    while (g_wifi_connected == 0) {
        printf("Waiting for WiFi connection...\r\n");
        sleep(1);
    }
    
    // WiFi 连接成功后，等待一小段时间确保网络稳定
    printf("WiFi Connected! Waiting 3 seconds for network stability...\r\n");
    sleep(3);

    // 初始化 MQTT 网络
    NetworkInit(&n);
    
    // 连接 MQTT 服务器 (TCP 连接)
    printf("Connecting to MQTT Broker: %s:%d ...\r\n", MQTT_BROKER, MQTT_PORT);
    int tcp_ret = NetworkConnect(&n, MQTT_BROKER, MQTT_PORT);
    if (tcp_ret != 0) {
        printf("TCP Connection to MQTT Broker Failed! ret=%d\r\n", tcp_ret);
        printf("Check your network, firewall, and MQTT broker settings.\r\n");
        return;
    }
    printf("TCP Connected to MQTT Broker.\r\n");
    
    // 分配 MQTT 缓冲区
    mqtt_buf = (unsigned char *)malloc(buf_size);
    mqtt_readbuf = (unsigned char *)malloc(buf_size);
    if (mqtt_buf == NULL || mqtt_readbuf == NULL) {
        printf("Failed to allocate memory for MQTT buffers\r\n");
        NetworkDisconnect(&n);
        return;
    }
    
    // 初始化 MQTT 客户端
    MQTTClientInit(&mq_client, &n, 1000, mqtt_buf, buf_size, mqtt_readbuf, buf_size);
    
    // 配置 MQTT 连接参数
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.MQTTVersion = 3; // MQTT v3.1
    data.clientID.cstring = MQTT_CLIENTID;
    data.username.cstring = MQTT_USER;
    data.password.cstring = MQTT_PASS;
    data.keepAliveInterval = 30;
    data.cleansession = 1;
    
    // 连接 MQTT 服务器
    int ret = MQTTConnect(&mq_client, &data);
    if (ret != 0) {
        printf("MQTT Connect Failed! Code: %d\r\n", ret);
        free(mqtt_buf);
        free(mqtt_readbuf);
        NetworkDisconnect(&n);
        return;
    }
    printf("MQTT Connected Successfully! User: %s\r\n", MQTT_USER);
    
    // 订阅主题 (可选，如果需要接收消息的话)
    ret = MQTTSubscribe(&mq_client, MQTT_TOPIC, 0, mqtt_msg_cb);
    if (ret != 0) {
        printf("MQTT Subscribe to %s Failed! Code: %d\r\n", MQTT_TOPIC, ret);
        // 订阅失败不影响发布，可以继续运行
    } else {
        printf("MQTT Subscribed to topic: %s\r\n", MQTT_TOPIC);
    }
    
    // 主循环
    while (1) {
        // 检查按键标志位
        if (g_f1_flag) {
            Publish_Msg("Button F1 Clicked!");
            g_f1_flag = 0; // 发布后清零标志位
        }
        if (g_f2_flag) {
            Publish_Msg("Button F2 Clicked!");
            g_f2_flag = 0; // 发布后清零标志位
        }
        
        // MQTTYield 是 MQTT 客户端的核心，必须定期调用
        // 它会处理网络读写、心跳保活、消息接收等
        // 参数是超时时间（毫秒），在此期间线程会阻塞
        MQTTYield(&mq_client, 50); 
    }
}

void AppEntry(void) {
    osThreadAttr_t attr;
    attr.name = "ButtonMqttTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240; // 增大栈大小，确保稳定运行
    attr.priority = 25;

    if (osThreadNew((osThreadFunc_t)ButtonMqttTask, NULL, &attr) == NULL) {
        printf("Failed to create ButtonMqttTask!\r\n");
    }
}

SYS_RUN(AppEntry);